package cz.data.domain.driver.jdbc.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import cz.data.common.annotation.DataInner;
import cz.data.common.database.datasource.AbstractJdbcDbQuery;
import cz.data.common.exception.DataException;
import cz.data.common.support.db.DbProperty;
import cz.data.common.support.db.core.PageResult;
import cz.data.common.support.db.driver.JdbcCustomOperation;
import cz.data.common.support.db.source.DataSourceFactory;
import cz.data.common.support.db.source.DataSourceRegistry;
import cz.data.common.support.db.source.DbQuery;
import cz.data.common.utils.PageUtil;
import cz.data.domain.metadata.model.MetadataUtil;
import cz.data.domain.metadata.rpc.MetadataFeign;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.sql.PreparedStatement;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

@Api(tags = {"Jdbc自定义API"})
@RestController
public class JdbcCustomController {

    @Resource
    MetadataFeign metadataFeign;

    @DataInner
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "SQL-指令")
    @PostMapping("/api/driver/jdbc/instruct")
    public PageResult<Map<String, Object>> instruct(@RequestBody @Valid JdbcCustomOperation operation) throws JSQLParserException {
        DbProperty property = Optional.of(operation.getSource())
                .map(metadataFeign::getMetadataSourceById)
                .map(MetadataUtil::dbProperty)
                .orElseThrow(() -> new DataException("API调用查询数据源出错"));
        DataSourceFactory factory = DataSourceRegistry.factory(property.getDbType());
        PageResult<Map<String, Object>> pageResult;
        String sql = operation.getCommand();
        JSONObject params = operation.getParams();
        Integer pageNum = operation.getPageNum();
        Integer pageSize = operation.getPageSize();
        PageUtil pageUtil = new PageUtil(pageNum, pageSize);
        Integer offset = pageUtil.getOffset();
        DbQuery dbQuery = factory.createDbQuery(property);
        Statement statement = CCJSqlParserUtil.parse(sql);
        if (statement instanceof Select) {
            pageResult = dbQuery.queryByPage(sql, params, offset, pageSize);
            pageResult.setPageNum(pageNum).setPageSize(pageSize);
        } else if (statement instanceof Insert ||
                statement instanceof Update ||
                statement instanceof Delete) {
            AbstractJdbcDbQuery jdbcDbQuery = (AbstractJdbcDbQuery) dbQuery;
            JdbcTemplate jdbcTemplate = jdbcDbQuery.getJdbcTemplate();
            NamedParameterJdbcTemplate namedJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
            Integer updateRows = namedJdbcTemplate.execute(sql, params, PreparedStatement::executeUpdate);
            Map<String, Object> row = Collections.singletonMap("rows", updateRows);
            pageResult = new PageResult<>(1, Collections.singletonList(row));
        } else {
            pageResult = new PageResult<>(0, Collections.emptyList());
        }
        return pageResult;
    }
}
